Fix cache key eviction #629
Conversation
…s evicting keys not added to the list of safeEvictionKeys
|
All contributors have signed the CLA ✍️ ✅ |
|
I have read the CLA Document and I hereby sign the CLA |
…or key eviction logic, fix usage of safeEvictionKey in OnyxCache
|
Going to assign @mountiny as they are involved in the original issue! |
|
Also waiting for @fabioh8010 review! |
| /** | ||
| * Check if a given key matches a pattern key | ||
| * @param configKey - Pattern that may contain a wildcard | ||
| * @param key - Key to test against the pattern | ||
| */ | ||
| private isKeyMatch(configKey: OnyxKey, key: OnyxKey): boolean { | ||
| const isCollectionKey = configKey.endsWith('_'); | ||
| return isCollectionKey ? Str.startsWith(key, configKey) : configKey === key; | ||
| } |
There was a problem hiding this comment.
Is this a copy of OnyxUtils.isKeyMatch? Can't we reuse instead?
There was a problem hiding this comment.
We cannot import OnyxUtils to OnyxCache as this produces dependency cycle
There was a problem hiding this comment.
Let's please extract this to another file that both OnyxUtils and OnyxCache can import, to avoid duplicate code
There was a problem hiding this comment.
We could think about splitting up the OnyxUtils file in general, because at the moment it's around ~1500 lines long and there's not that much inter-dependent state between the functions
There was a problem hiding this comment.
But maybe let's do that in a follow-up PR 😅
| // When a new connection for a safe eviction key happens | ||
| Onyx.connect({key: `${ONYX_KEYS.COLLECTION.MOCK_COLLECTION}10`, callback: jest.fn()}); | ||
| }) | ||
| .then(waitForPromisesToResolve) |
There was a problem hiding this comment.
This is needed as we need to wait till onyx connect resolves to check if its in the cache
There was a problem hiding this comment.
This is needed as we need to wait till onyx connect resolves to check if its in the cache
That sounds good to me 👍🏼
|
Also cc @chrispader for visibility |
…st-for-keys-eviction-implementation
|
@kubabutkiewicz can you please provide videos for this PR? |
|
@jjcoffee will you be able to do a checklist/ test this change in App please? |
|
@mountiny Yeah, I am on it |
|
@mountiny Yessir! |
Reviewer Checklist
Screenshots/VideosAndroid: Nativeandroid-app-2025-04-25_15.04.04.mp4Android: mWeb Chromeandroid-chrome-2025-04-25_15.09.55.mp4iOS: Nativeios-app-2025-04-25_14.24.18.mp4iOS: mWeb Safariios-safari-2025-04-25_14.28.30.mp4MacOS: Chrome / Safaridesktop-chrome-2025-04-25_13.49.47.mp4MacOS: Desktopdesktop-app-2025-04-25_13.55.21.mp4 |
This comment was marked as resolved.
This comment was marked as resolved.
|
@jjcoffee in the App you need to change here https://github.com/Expensify/App/blob/5f5f4a0857a5211dc00b61ea77e93ea5a20bc887/src/setup/index.ts#L31 |
This comment was marked as resolved.
This comment was marked as resolved.
|
@jjcoffee No its not, let me check it |
|
@jjcoffee Issue fixed |
|
@kubabutkiewicz Nice thanks, tests well now! Are we ignoring the perf test fail? |
|
@jjcoffee I think yes based on Fabio comment #629 (comment) |
|
@fabioh8010 how can we be sure they failed due to flakiness? |
| () => false, | ||
| () => Promise.resolve(new Set(Object.keys(data))), |
There was a problem hiding this comment.
@kubabutkiewicz please move () => false and () => Promise.resolve(new Set(Object.keys(data))) to outside measureAsyncFunction
There was a problem hiding this comment.
@fabioh8010 I am not sure what do you mean, something like that?

There was a problem hiding this comment.
Yeah it's okay this way!
There was a problem hiding this comment.
ok thanks, pushed a change
Let's wait for Kuba to address the last comment and I will manually analyse the next Reassure run |
|
Reassure output of significant changes: This one seems to be the only one "significant" related to the PR Still, I don't think a +1.4 ms deviation is something to worry about. BTW, I'm working on a improvement for Reasure workflow measurements here. |
|
@kubabutkiewicz Could you merge this again with |
…st-for-keys-eviction-implementation
|
@fabioh8010 Done 😄 |
mountiny
left a comment
There was a problem hiding this comment.
Thanks, looks nice and clean! One question just to make sure we dont miss anything
| ```js | ||
| Onyx.init({ | ||
| safeEvictionKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], | ||
| evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], |
There was a problem hiding this comment.
Will this require any migration?
There was a problem hiding this comment.
The only thing we need to do is just change the parameter name in the app. I am also thinking we should add more keys in the App which are evictable. Like NYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS tested it already and there seems to not be any disadvantages
There was a problem hiding this comment.
Ok thanks, feel free to work on the bump PR
Details
This PR renames safeEvictionKeys to evictableKeys throughout the codebase for clearer naming that better reflects the parameter's purpose. It also refactors the key eviction system by:
These changes make Onyx's storage management more predictable and maintainable.
Related Issues
Expensify/App#59913
Automated Tests
Added the tests verifying that only keys added to
evictableKeysare evicted from cache.Manual Tests
evictableKeysAuthor Checklist
### Related Issuessection aboveTestssectiontoggleReportand notonIconClick)myBool && <MyComponent />.STYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)/** comment above it */thisproperly so there are no scoping issues (i.e. foronClick={this.submit}the methodthis.submitshould be bound tothisin the constructor)thisare necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);ifthis.submitis never passed to a component event handler likeonClick)Avataris modified, I verified thatAvataris working as expected in all cases)mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
android.mp4
Android: mWeb Chrome
android-web.mp4
iOS: Native
ios.mp4
iOS: mWeb Safari
MacOS: Chrome / Safari
wev.mp4
MacOS: Desktop
desktop.mp4